﻿// ***********************************************************************
// Assembly         : SecurityLayer
// Author           : LJO+01 (Laurent Jordi)
// Created          : 06-05-2013
// Last Modified By : LJO+01 (Laurent Jordi)
// Last Modified On : 06-05-2013
// ***********************************************************************
// <copyright file="InnovacallAuthorizeAttribute.cs" company="Copyright © Innovacall 2011">
//     Copyright (c) Copyright © Innovacall 2011. All rights reserved.
// </copyright>
// <summary></summary>
// ***********************************************************************
using System;
using System.Security.Principal;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;

namespace InnovaApp.Layers.SecurityLayer.RoleAndMembershipProvider
{

    /// <summary>
    /// Usage in MVC Page (Source http://schotime.net/blog/index.php/2009/02/17/custom-authorization-with-aspnet-mvc/)
    /// [InnovaCMSAuthorizeAttribute(Roles=enMembershipRoles.Admin|enMembershipRoles.HelpDesk)]
    /// public ActionResult Index()
    /// {
    /// return View();
    /// }
    /// </summary>
    public class InnovacallAuthorizeAttribute : AuthorizeAttribute
    {
        //public new enMembershipRoles bershi
        /// <summary>
        /// The roles
        /// </summary>
        public new enInnovacallRoles Roles;

        /// <summary>
        /// The failed roles auth
        /// </summary>
        private bool FailedRolesAuth = false;

        /// <summary>
        /// Caches the validation handler.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="data">The data.</param>
        /// <param name="validationStatus">The validation status.</param>
        public void CacheValidationHandler(HttpContext context,
                                            object data,
                                            ref HttpValidationStatus validationStatus)
        {
            validationStatus = OnCacheAuthorization(new HttpContextWrapper(context));
        }

        /// <summary>
        /// En cas de substitution, fournit un point d'entrée aux contrôles des autorisations personnalisés.
        /// </summary>
        /// <param name="httpContext">Contexte HTTP qui encapsule toutes les informations spécifiques à HTTP concernant une requête HTTP individuelle.</param>
        /// <returns>true si l'utilisateur est autorisé ; sinon, false.</returns>
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            var isAuthorized = base.AuthorizeCore(httpContext);
            if (isAuthorized)
            {
                var authCookie = httpContext.Request.Cookies[FormsAuthentication.FormsCookieName];
                if (authCookie != null)
                {
                    var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
                    var identity = new GenericIdentity(authTicket.Name, "Forms");
                    var principal = new GenericPrincipal(identity, new string[] { });
                    httpContext.User = principal;
                }
            }
            return isAuthorized;
        }

        /// <summary>
        /// Appelée lorsqu'un processus demande une autorisation.
        /// </summary>
        /// <param name="filterContext">Contexte de filtre qui encapsule les informations relatives à l'utilisation de <see cref="T:System.Web.Mvc.AuthorizeAttribute" />.</param>
        /// <exception cref="System.ArgumentNullException">filterContext</exception>
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            if (filterContext == null)
            {
                throw new ArgumentNullException("filterContext");
            }

            if (AuthorizeCore(filterContext.HttpContext))
            {
                /// ToDo : LJO Customize AuthorizeAttribute 
                SetCachePolicy(filterContext);
            }
            else if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
            {
                // auth failed, redirect to login page
                filterContext.Result = new HttpUnauthorizedResult();
            }
            else
            {
                /// ToDo : LJO Customize AuthorizeAttribute : handle a different case than not authenticated

            }
        }



        /// <summary>
        /// Sets the cache policy.
        /// </summary>
        /// <param name="filterContext">The filter context.</param>
        protected void SetCachePolicy(AuthorizationContext filterContext)
        {
            // ** IMPORTANT **
            // Since we're performing authorization at the action level, the authorization code runs
            // after the output caching module. In the worst case this could allow an authorized user
            // to cause the page to be cached, then an unauthorized user would later be served the
            // cached page. We work around this by telling proxies not to cache the sensitive page,
            // then we hook our custom authorization code into the caching mechanism so that we have
            // the final say on whether a page should be served from the cache.
            HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
            cachePolicy.SetProxyMaxAge(new TimeSpan(0));
            cachePolicy.AddValidationCallback(CacheValidationHandler, null /* data */);
        }
    }
}
